package com.fafu.common.web.aop;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * 基于AOP的统一日志处理
 *
 * @author hc
 */
@Slf4j
@Aspect
@Component
public class LogAOP {
    @Pointcut("execution(* com.fafu..controller..*.*(..))")
    public void fun() {
    }

    /**
     * 设置before方法会在、com.wego.controller包及其子包下的、任意访问控制修饰符修饰的、返回值为任意类型的、包含任何多个参数的、任意方法、执行之前执行
     */
    @Before("fun()")
    public void doBefore() {
        final long start = System.currentTimeMillis();
        log.info("访问开始时间：" + start);
    }

    @After("fun()")
    public void doAfter() {
        final long end = System.currentTimeMillis();
        log.info("访问结束时间：" + end);
    }

    @AfterReturning(returning = "res", pointcut = "fun()")
    public void doAfterReturing(JoinPoint joinPoint, Object res) {
        final String fullMethodName = getFullMethodName(joinPoint);
        final Object[] args = joinPoint.getArgs();
        log.info("访问的方法为：" + fullMethodName + "参数名：" + Arrays.toString(args) + "\t结果为：" + res);
    }

    @AfterThrowing(throwing = "e", pointcut = "fun()")
    public void doAfterThrowing(JoinPoint joinPoint, Throwable e) {
        final String fullMethodName = getFullMethodName(joinPoint);
        final Object[] args = joinPoint.getArgs();
        log.info("访问 " + fullMethodName + "参数名：" + Arrays.toString(args) + " 出现异常：" + e);
    }

    private String getFullMethodName(JoinPoint joinPoint) {
        return joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName();
    }

}
